import pandas as pd
from pymongo import MongoClient
from tools import time_to_minutes,calculate_load_time,calculate_start_time,plan_to_result
from aluminum import generate_a_schedule,assign_aluminum_tasks
from single_top import assign_single_top_tasks
from double_zero import assign_double_zero_tasks
from mongo_database import update_mongodb


# ----------------------
# 定义今日运输任务需求
# ----------------------
# ----------------------
# 读取交互式计划 & 休息名单（来自 input.py 生成的 parsed_plan.json）
# ----------------------
import os, json


plan_file = 'parsed_plan.json'
if not os.path.exists(plan_file):
    raise FileNotFoundError("未找到 parsed_plan.json。请先运行 input.py 生成该文件。")

with open(plan_file, 'r', encoding='utf-8') as f:
    payload = json.load(f)

plan = payload.get('plan', {})
rest_names = payload.get('rest_names', [])
changde_transfer_names = payload.get('changde_transfer_names', [])

def _safe_get(d, key, default):
    return d[key] if key in d and d[key] is not None else default

# 将 input.py 的结构映射到 time_plan 期望的 today_tasks 结构
today_tasks = {
    '铝卷': {'count': _safe_get(plan.get('铝卷', {}), 'count', 0)},
    # 注意：下面两个 times 实际承载“装车时间”，算法稍后会用 calculate_start_time 推发车
    '铝棒': {'times': _safe_get(plan.get('铝棒', {}), 'load_time', [])},
    '单顶': {'times': _safe_get(plan.get('单顶', {}), 'load_time', [])},
    '双零箔': {
        'count': _safe_get(plan.get('双零箔', {}), 'count', 0),
        # time_plan 里需要一个统一装车时间字符串，这里取列表第一个，若没有则默认 7:50
        'load_time': (_safe_get(plan.get('双零箔', {}), 'load_time', ['7:50']) or ['7:50'])[0]
    },
    # input.py 叫“铝箔废铝”，time_plan 里叫“废铝卷”
    '废铝卷': {'count': _safe_get(plan.get('铝箔废铝', {}), 'count', 0)},
    '常德甩挂人员': {'name':str(changde_transfer_names[0])}
}
print(">>> 已载入交互式计划 today_tasks：", today_tasks)
print(">>> 休息名单：", rest_names)


# ----------------------
# 初始化车辆
# ----------------------
scania_count = 8
benche_count = 2
jie_count = 3
vehicles = []
for i in range(8):
    vehicles.append({'id': f'S{i + 1}', 'type': 'SCANIA', 'available_time': -540, 'used': False})
for i in range(2):
    vehicles.append({'id': f'B{i + 1}', 'type': '奔驰', 'available_time': -540, 'used': False})
for i in range(3):
    vehicles.append({'id': f'J{i + 1}', 'type': '解放', 'available_time': -540, 'used': False})
van_vehicles = []
for i in range(3):
    van = {'id': f'X{i + 1}', 'type': '厢车', 'available_time': -540, 'used': False}
    vehicles.append(van)
    van_vehicles.append(van)

# ----------------------
# 处理废铝铝卷任务
# ----------------------
special_aluminum_roll_tasks = [
    {'driver_name': '', 'plate_number': '', 'vehicle_id': 'S1', 'vehicle_type': 'SCANIA',
     'departure_time': '7:00', 'load_time': '晚上装车', 'cargo_type': '铝卷', 'is_transfer': '否'},
    {'driver_name': '', 'plate_number': '', 'vehicle_id': 'S2', 'vehicle_type': 'SCANIA',
     'departure_time': '7:00', 'load_time': '晚上装车', 'cargo_type': '铝卷', 'is_transfer': '否'},
    {'driver_name': '', 'plate_number': '', 'vehicle_id': 'S3', 'vehicle_type': 'SCANIA',
     'departure_time': '7:00', 'load_time': '晚上装车', 'cargo_type': '铝卷', 'is_transfer': '否'}
]
special_aluminum_tasks = special_aluminum_roll_tasks[:today_tasks['废铝卷']['count']]
for task in special_aluminum_tasks:
    special_vehicle = next((v for v in vehicles if v['id'] == task['vehicle_id']), None)
    if special_vehicle:
        special_vehicle['used'] = True
        special_vehicle['available_time'] = time_to_minutes('20:00')

# ----------------------
# 处理铝棒和单顶任务
# ----------------------
tasks = []
for time in today_tasks['铝棒']['times']:
    tasks.append({'type': '铝棒', 'time': time})
for time in today_tasks['单顶']['times']:
    tasks.append({'type': '单顶', 'time': time})
for i in range(today_tasks['双零箔']['count']):
    tasks.append({'type': '双零箔', 'time':today_tasks['双零箔']['load_time']})
# ----------------------
# 货物铝棒、单顶和双零箔
# ----------------------
schedule = []
for task in sorted(tasks, key=lambda x: time_to_minutes(x['time'])):
    task_time_str = task['time']
    task_time = time_to_minutes(task_time_str)
    selected = None
    if task['type'] in ['铝棒', '单顶']:
        j_candidates = [v for v in vehicles if v['type'] == '解放' and v['available_time'] + 540 <= task_time]
        selected = j_candidates[0] if j_candidates else None
        if not selected:
            scania_benz = [v for v in vehicles if
                           v['type'] in ['SCANIA', '奔驰'] and v['available_time'] + 540 <= task_time]
            selected = scania_benz[0] if scania_benz else None
    if task['type'] == '双零箔':
        j_candidates = [v for v in vehicles if v['type'] == '厢车' and v['available_time'] + 540 <= task_time]
        selected = j_candidates[0] if j_candidates else None
        if not selected:
            scania_benz = [v for v in vehicles if
                           v['type'] in ['SCANIA', '奔驰'] and v['available_time'] + 540 <= task_time]
            selected = scania_benz[0] if scania_benz else None
    if selected:
        schedule.append({
            'driver_name': '', 'plate_number': '', 'vehicle_id': selected['id'],
            'vehicle_type': selected['type'], 'departure_time': calculate_start_time(task_time_str,task['type']),
            'load_time': task_time_str, 'cargo_type': task['type'],
            'is_transfer': '否'
        })
        selected['available_time'] = time_to_minutes(schedule[-1]['departure_time'])
        selected['used'] = True


# ----------------------
# 处理剩余铝卷任务
# ----------------------
A_count = today_tasks['铝卷']['count'] - today_tasks['废铝卷']['count']
scania_benz = [v for v in vehicles if v['type'] in ['SCANIA', '奔驰']]
available_a_vehicles = [v for v in scania_benz if not v['used']]
need_transfer = max(0, A_count - len(available_a_vehicles))
a_tasks = generate_a_schedule(available_a_vehicles[:A_count], need_transfer)
for task in a_tasks:
    selected = next((v for v in vehicles if v['id'] == task['vehicle_id']), None)
    if selected:
        schedule.append({
            'driver_name': '', 'plate_number': '', 'vehicle_id': selected['id'],
            'vehicle_type': selected['type'], 'departure_time': task['time'],
            'load_time': calculate_load_time(task['time']), 'cargo_type': task['type'],
            'is_transfer': '否'
        })
        selected['available_time'] = time_to_minutes(task['time'])
        selected['used'] = True

# ----------------------
# 更新接车状态
# ----------------------
vehicle_trips = {}
for item in schedule:
    vid = item['vehicle_id']
    vehicle_trips[vid] = vehicle_trips.get(vid, 0) + 1
for item in schedule:
    if vehicle_trips[item['vehicle_id']] >= 2:
        item['is_transfer'] = '是'


# ----------------------
# 合并所有任务并排序
# ----------------------
all_tasks = schedule + special_aluminum_tasks
all_tasks.sort(key=lambda x: time_to_minutes(x['departure_time']) if x['departure_time'] else float('inf'))

# ----------------------
# 转换为DataFrame并保存为CSV
# ----------------------
df = pd.DataFrame(all_tasks)
df = df[['driver_name', 'plate_number', 'vehicle_id', 'vehicle_type', 'departure_time', 'load_time', 'cargo_type',
         'is_transfer']]
df.to_csv('今日运输任务调度总表.csv', index=False, encoding='utf-8-sig')
print("已生成CSV格式的今日运输任务调度总表.csv")


# ----------------------
# MongoDB数据加载
# ----------------------
MONGO_URI = "mongodb://172.40.10.127:27017/"
DB_NAME = "innerVehicle"
VEH_COLL = "vehicle_test"
DRV_COLL = "driver_test"
client = MongoClient(MONGO_URI)
db = client[DB_NAME]
db_update = client[DB_NAME]
collection = db_update['driver_test']

update_mongodb(collection)

# 让休息人员,甩挂人员不参与后续任何任务分配
assigned_drivers = set(rest_names)
assigned_vehicles = set()
assigned_drivers.add(today_tasks['常德甩挂人员']['name'])
driver_list = rest_names
driver_list.append(today_tasks['常德甩挂人员']['name'])

# 车辆：DB侧直接排除维修/保养中的车，兼容多种字段命名
vehicle_query = {
    "$and": [
        {"$or": [{"is_repairing": {"$ne": True}}, {"is_repairing": {"$exists": False}}]},
        {"$or": [{"under_maintenance": {"$ne": True}}, {"under_maintenance": {"$exists": False}}]},
        {"$or": [{"status": {"$exists": False}}, {"status": {"$nin": ["维修", "修理", "maintenance", "repair"]}}]},
        {"$or": [{"is_active": {"$ne": False}}, {"is_active": {"$exists": False}}]}  # 如果有激活标记，则排除不激活
    ]
}
print(vehicle_query)
vehicle_docs = list(db[VEH_COLL].find(vehicle_query, {"_id": 0}))
driver_docs = list(db[DRV_COLL].find({}, {"_id": 0}))
vehicle_df = pd.DataFrame(vehicle_docs)
driver_df = pd.DataFrame(driver_docs)

# 处理单顶任务
single_top_results, assigned_drivers, assigned_vehicles = assign_single_top_tasks(df, driver_df, vehicle_df, assigned_drivers, assigned_vehicles)
# 分配双零箔任务
double_zero_results, assigned_drivers, assigned_vehicles = assign_double_zero_tasks(df, driver_df, vehicle_df, assigned_drivers, assigned_vehicles)
# 分配铝棒和铝卷任务
aluminum_results, assigned_drivers, assigned_vehicles = assign_aluminum_tasks(df, vehicle_df, driver_df, assigned_drivers, assigned_vehicles)

time_plan_df = pd.DataFrame(single_top_results + aluminum_results + double_zero_results)
result_df = plan_to_result(time_plan_df)

print('未安排运输任务的人员名单：')
print(driver_df[~driver_df['driver_name'].isin(assigned_drivers)]['driver_name'])
print('未安排运输任务的车辆名单：')
print(assigned_vehicles)
print(vehicle_df[~vehicle_df['plate_number'].isin(assigned_vehicles)])
print(result_df)
result_df.to_excel('每日排班分配结果.xlsx', index=False)



# mongodb数据库更新
for data in driver_list:
    result =collection.update_one(
        {'driver_name': data},
        {
            "$push": {
                "last_4days_departure_times": {
                    "$each": [None],
                    "$slice": -4  # 只保留最后4个元素
                }
            },
            "$inc": {"month_double_zero_count": 1}
        }  # 更新操作
    )
for _,data in result_df.iterrows():
    # 更新第一个匹配的文档
    if data['货物类型'] == '双零箔':
        result = collection.update_one(
            {"driver_name": data['司机姓名']},  # 查询条件
            {
                "$push": {
                    "last_4days_departure_times": {
                        "$each": [data['装货时间']],
                        "$slice": -4  # 只保留最后4个元素
                    }
                },
                "$inc": {"month_double_zero_count": 1}
            }  # 更新操作
        )
    elif data['货物类型'] == '单顶':
        result = collection.update_one(
            {"driver_name": data['司机姓名']},  # 查询条件
            {
                "$push": {
                    "last_4days_departure_times": {
                        "$each": [data['发车时间']],
                        "$slice": -4  # 只保留最后4个元素
                    }
                },
                "$inc": {"season_single_top_count": 1}
            }  # 更新操作
        )
    else:
        if collection["driver_name"] == data['司机姓名']:
            print(data)
        result = collection.update_one(
            {"driver_name": data['司机姓名']},
            {
                "$push": {
                    "last_4days_departure_times": {
                        "$each": [data['发车时间']],
                        "$slice": -4  # 只保留最后4个元素
                    }
                }
            }
        )
print(f"匹配了 {result.matched_count} 个文档，修改了 {result.modified_count} 个文档")
















